package com.carefree.system.common.aop;

import com.alibaba.fastjson2.JSONObject;
import com.carefree.common.utils.HttpContextUtils;
import com.carefree.common.utils.IpUtils;
import com.carefree.system.common.annotation.SystemLog;
import com.carefree.system.modules.admin.entity.OperLogEntity;
import com.carefree.system.modules.admin.service.OperLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * @ClassName:SystemLogAspect
 * @Description: 操作日志切面
 * @Author Tengbin tengbin234@163.com
 */
@Aspect
@Component
@Slf4j
public class SystemLogAspect {

    @Resource(name = "operLogService")
    private OperLogService operLogService;


    @AfterReturning(pointcut = "@annotation(systemLog)", returning = "returnVal")
    public void around(JoinPoint joinPoint, SystemLog systemLog, Object returnVal) {
        // 保存操作日志信息
        saveOperLog(joinPoint, systemLog, returnVal, null);
    }

    @AfterThrowing(value = "@annotation(systemLog)", throwing = "ex")
    public void doAfterThrowing(JoinPoint joinPoint, SystemLog systemLog, Exception ex) {
        saveOperLog(joinPoint, systemLog, ex, null);
    }


    /**
     * 保存操作日志信息
     *
     * @param joinPoint 切入点
     * @param returnVal 返回参数
     * @param ex        抛出的异常
     */
    private void saveOperLog(JoinPoint joinPoint, SystemLog systemLog, Object returnVal, Exception ex) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();

        OperLogEntity operLogEntity = new OperLogEntity();

        // 模块标题,即注解上的value值
        operLogEntity.setTitle(systemLog.value());
        // 业务类型
        operLogEntity.setBusinessType(systemLog.businessType().name());
        // 操作类别
        operLogEntity.setOperatorType(systemLog.operatorType().name());

        //方法名称,格式:全限定名.方法名()
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = method.getName();
        operLogEntity.setMethod(className + "." + methodName + "()");

        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        // 请求方式
        operLogEntity.setRequestMethod(request.getMethod());

        // 操作人员
        String userName = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        operLogEntity.setOperName(userName);

        // 请求url
        operLogEntity.setOperUrl(request.getRequestURI());

        // 主机地址
        operLogEntity.setOperIp(IpUtils.getIpAddress(request));

        // 请求参数
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            String argJsonStr = JSONObject.toJSONString(arg);
            operLogEntity.setOperParam(argJsonStr);
        }

        // 返回参数
        String returnValJsonStr = JSONObject.toJSONString(returnVal);
        operLogEntity.setJsonResult(returnValJsonStr);

        // 操作状态
        operLogEntity.setStatus(ex != null ? 1 : 0);
        // 错误消息
        operLogEntity.setErrorMsg(ex != null ? ex.getMessage() : "");
        // 操作时间
        operLogEntity.setOperTime(new Date());

        // 保存操作日志
        operLogService.save(operLogEntity);
    }


}
